package org.softmed.action.pool;

import java.util.ArrayList;
import java.util.List;
import org.softmed.action.Action;
import org.softmed.action.workarea.WorkArea;

public class ActionPool {
	int start = 10;
	int inc = 5;
	int count = 10;

	protected ActionConfigurator actionConfigurator;

	List<Action> available = new ArrayList<Action>();
	List<Action> busy = new ArrayList<Action>();
	Action original;

	List<ReturnToActionPool> returns = new ArrayList<ReturnToActionPool>();
	ReturnToActionPool rtap;
	Action action;

	public void rebuild() throws Throwable {
		clear();
		addClones(start);
	}

	public synchronized Action getActionFromPool() throws Throwable {
		if (available.size() == 0)
			addClones(inc);
		action = available.remove(0);
		busy.add(action);

		return action;
	}

	synchronized void returnActionToPool(Action action, ReturnToActionPool rtap) {
		busy.remove(action);
		available.add(action);
		action.getWorkArea().clear();
	}

	protected void addClones(int number) throws Throwable {

		Action clone;
		for (int i = 0; i < number; i++) {
			clone = original.clone();
			clone.setWorkArea(new WorkArea());

			if (actionConfigurator != null)
				actionConfigurator.configure(original, clone);

			available.add(clone);

			rtap = new ReturnToActionPool();
			rtap.setActionPool(this);
			returns.add(rtap);
			rtap.setAction(clone);
			clone.getDisposing().addStep(rtap);
		}
		count += number;
	}

	public int getStart() {
		return start;
	}

	public void setStart(int start) {
		this.start = start;
		count = start;
	}

	public int getInc() {
		return inc;
	}

	public void setInc(int inc) {
		this.inc = inc;
	}

	public Action getOriginal() {
		return original;
	}

	public void setOriginal(Action original) {
		this.original = original;
	}

	public int getCount() {
		return count;
	}

	public void clear() {
		available.clear();
		busy.clear();
		for (ReturnToActionPool rtap : returns) {
			rtap.setAction(null);
			rtap.setActionPool(null);
		}
		returns.clear();

		count = 0;
	}

	public ActionConfigurator getActionConfigurator() {
		return actionConfigurator;
	}

	public void setActionConfigurator(ActionConfigurator actionConfigurator) {
		this.actionConfigurator = actionConfigurator;
	}

}
